using HtERP.Data;
namespace HtERP.Services
{
    /// <summary>
    /// 备份调度服务的后台服务实现
    /// </summary>
    public class BackupSchedulerHostedService : BackgroundService
    {
        private IBackupScheduleService? _backupSchedulerService;
        private readonly ILogger<BackupSchedulerHostedService> _logger;
        private readonly IServiceScopeFactory _scopeFactory;

        // 定时器管理
        private readonly Dictionary<string, Timer> _timers = new Dictionary<string, Timer>();
        private readonly object _lock = new object();
        private bool _isRunning = false;
        public bool IsRunning => _isRunning;
        public BackupSchedulerHostedService(
            ILogger<BackupSchedulerHostedService> logger,
            IServiceScopeFactory scopeFactory)
        {
            _logger = logger;
            _scopeFactory = scopeFactory;
        }

        private void CreateBackupSchedulerService()
        {
            // 创建一个作用域来获取Scoped服务
            using (var scope = _scopeFactory.CreateScope())
            {
                // 直接获取DbBackupGUI中的备份调度服务
                _backupSchedulerService = scope.ServiceProvider.GetRequiredService<IBackupScheduleService>();
            }
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("备份调度后台服务正在启动");

            try
            {
                // 创建备份调度服务实例
                CreateBackupSchedulerService();
                
                // 加载备份计划
                await LoadBackupSchedulesAsync();
                
                // 注意：不自动启动备份调度服务，等待用户在index页面点击启动按钮后才开始备份
                _logger.LogInformation("备份调度服务已初始化，等待用户手动启动");

                // 等待取消令牌
                await Task.Delay(Timeout.Infinite, stoppingToken);
            }
            catch (OperationCanceledException)
            {
                // 当应用程序关闭时，此异常会被抛出
                _logger.LogInformation("备份调度后台服务正在停止");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "备份调度后台服务发生异常");
            }
            finally
            {
                // 停止所有定时器
                StopAllTimers();
                
                // 如果服务已经启动，则停止它
                if (_backupSchedulerService != null)
                {
                    _backupSchedulerService.Stop();
                }
                
                _logger.LogInformation("备份调度服务已停止");
            }
        }

        private async Task LoadBackupSchedulesAsync()
        {
            try
            {
                _logger.LogInformation("正在从数据库加载备份计划");
                
                // 使用IServiceScopeFactory创建作用域并获取IBackupScheduleService
                using (var scope = _scopeFactory.CreateScope())
                {
                    var dbScheduleService = scope.ServiceProvider.GetRequiredService<IBackupScheduleService>();
                    var dbSchedules = await dbScheduleService.GetAllSchedulesAsync();
                    
                    foreach (var dbSchedule in dbSchedules)
                    {
                        if (dbSchedule.Enabled && dbSchedule.DbConfig != null && !string.IsNullOrEmpty(dbSchedule.BackupDirectory))
                        {
                            _logger.LogInformation("已加载备份计划: {ScheduleName}", dbSchedule.Name);
                        }
                    }

                    _logger.LogInformation("已加载 {Count} 个备份计划", dbSchedules.Count);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "加载备份计划时出错");
            }
        }

        /// <summary>
        /// 启动所有定时器
        /// </summary>
        public void StartAllTimers()
        {
            lock (_lock)
            {
                if (_isRunning)
                {
                    _logger.LogInformation("定时器已经在运行中");
                    return;
                }

                _isRunning = true;
                _logger.LogInformation("开始启动所有备份计划的定时器");
            }

            // 创建一个临时任务来加载备份计划
            Task.Run(async () =>
            {
                try
                {
                    using (var scope = _scopeFactory.CreateScope())
                    {
                        var dbScheduleService = scope.ServiceProvider.GetRequiredService<IBackupScheduleService>();
                        var dbSchedules = await dbScheduleService.GetAllSchedulesAsync();

                        _logger.LogInformation("从数据库获取了 {Count} 个备份计划", dbSchedules.Count);

                        // 为所有启用的备份计划启动定时器
                        foreach (var schedule in dbSchedules)
                        {
                            if (schedule.Enabled && schedule.DbConfig != null && !string.IsNullOrEmpty(schedule.BackupDirectory))
                            {
                                StartScheduleTimer(schedule.Name, schedule);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "从数据库获取备份计划并启动定时器时发生异常");
                }
            });
        }

        /// <summary>
        /// 停止所有定时器
        /// </summary>
        public void StopAllTimers()
        {
            lock (_lock)
            {
                if (!_isRunning)
                {
                    _logger.LogInformation("定时器已经停止");
                    return;
                }

                _isRunning = false;
                _logger.LogInformation("开始停止所有备份计划的定时器");

                // 停止并释放所有定时器
                foreach (var timer in _timers.Values)
                {
                    timer.Dispose();
                }
                _timers.Clear();
            }
        }

        /// <summary>
        /// 启动指定计划的定时器
        /// </summary>
        public void StartScheduleTimer(string scheduleName, BackupSchedule schedule)
        {
            if (schedule == null)
            {
                _logger.LogWarning("找不到备份计划: {ScheduleName}", scheduleName);
                return;
            }

            // 停止已有的定时器
            StopScheduleTimer(scheduleName);

            if (!schedule.Enabled || !_isRunning)
            {
                _logger.LogInformation("备份计划 '{ScheduleName}' 未启用或服务未运行", scheduleName);
                return;
            }

            try
            {
                // 使用非异步回调包装异步操作
                TimerCallback callback = (state) =>
                {
                    try
                    {
                        // 创建一个新的任务来处理备份
                        Task.Run(async () =>
                        {
                            try
                            {
                                _logger.LogInformation("定时器触发备份: {ScheduleName}", scheduleName);
                                await ExecuteBackupAsync(scheduleName);
                            }
                            catch (Exception ex)
                            {
                                _logger.LogError(ex, "定时器执行备份时发生异常: {Message}", ex.Message);
                            }
                        });
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "定时器回调设置时发生异常: {Message}", ex.Message);
                    }
                };

                // 根据备份类型设置定时器
                if (schedule.BackupIntervalMinutes > 0)
                {
                    // 间隔时间备份
                    _logger.LogInformation("设置间隔时间备份: {ScheduleName}, 间隔 {Interval} 分钟", 
                        scheduleName, schedule.BackupIntervalMinutes);
                    // 为每个计划设置随机的启动延迟
                    int delay = new Random().Next(1000, 5000);
                    _timers[scheduleName] = new Timer(callback, null, delay, schedule.BackupIntervalMinutes * 60000);
                }
                else if (schedule.ScheduledBackupTimes != null && schedule.ScheduledBackupTimes.Count > 0)
                {
                    // 每日定时备份
                    _logger.LogInformation("设置每日定时备份: {ScheduleName}", scheduleName);
                    ScheduleDailyBackup(scheduleName, schedule);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "启动定时器时发生异常: {Message}", ex.Message);
            }
        }

        /// <summary>
        /// 停止指定计划的定时器
        /// </summary>
        public void StopScheduleTimer(string scheduleName)
        {
            lock (_lock)
            {
                if (_timers.TryGetValue(scheduleName, out var timer))
                {
                    timer.Dispose();
                    _timers.Remove(scheduleName);
                    _logger.LogInformation("已停止备份计划的定时器: {ScheduleName}", scheduleName);
                }
            }
        }

        /// <summary>
        /// 安排每日定时备份
        /// </summary>
        private void ScheduleDailyBackup(string scheduleName, BackupSchedule schedule)
        {
            try
            {
                // 计算下一个备份时间
                var now = DateTime.Now;
                DateTime nextBackupTime = DateTime.MaxValue;

                foreach (var timeString in schedule.ScheduledBackupTimes)
                {
                    if (TimeSpan.TryParse(timeString, out TimeSpan backupTime))
                    {
                        var nextTime = new DateTime(now.Year, now.Month, now.Day, backupTime.Hours, backupTime.Minutes, 0);
                        if (nextTime <= now)
                        {
                            // 如果今天的备份时间已过，安排到明天
                            nextTime = nextTime.AddDays(1);
                        }

                        if (nextTime < nextBackupTime)
                        {
                            nextBackupTime = nextTime;
                        }
                    }
                    else
                    {
                        _logger.LogWarning("无效的备份时间格式: {TimeString}，计划: {ScheduleName}", timeString, scheduleName);
                    }
                }

                if (nextBackupTime != DateTime.MaxValue)
                {
                    // 计算时间间隔
                    var interval = nextBackupTime - now;
                    _logger.LogInformation("下次备份时间: {Time}", nextBackupTime.ToString());

                    // 设置一次性定时器，备份完成后再设置下一次
                    TimerCallback callback = (state) =>
                    {
                        try
                        {
                            _logger.LogInformation("定时器触发备份回调: {ScheduleName}", scheduleName);
                            // 立即执行备份任务，不使用Task.Run包装以避免线程池问题
                            var backupTask = ExecuteBackupAsync(scheduleName);
                            // 等待备份完成后安排下一次备份
                            backupTask.ContinueWith(async task =>
                            {
                                try
                                {
                                    // 无论备份成功与否，都安排下一次备份
                                    // 先获取更新后的计划，然后再获取锁
                                    BackupSchedule updatedSchedule = null;
                                    try
                                    {
                                        using (var scope = _scopeFactory.CreateScope())
                                        {
                                            var dbScheduleService = scope.ServiceProvider.GetRequiredService<IBackupScheduleService>();
                                            var dbSchedules = await dbScheduleService.GetAllSchedulesAsync();
                                            updatedSchedule = dbSchedules.FirstOrDefault(s => s.Name == scheduleName);
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        _logger.LogError(ex, "从数据库获取更新后的备份计划时发生异常: {ScheduleName}", scheduleName);
                                    }

                                    // 获取锁来安全地访问共享资源
                                    lock (_lock)
                                    {
                                        // 确保服务仍在运行
                                        if (_isRunning && updatedSchedule != null && updatedSchedule.Enabled)
                                        {
                                            ScheduleDailyBackup(scheduleName, updatedSchedule);
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    _logger.LogError(ex, "安排下一次备份时发生异常: {Message}", ex.Message);
                                }
                            });
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, "定时器回调执行时发生异常: {Message}", ex.Message);
                        }
                    };

                    // 确保定时器被正确存储，防止被垃圾回收
                    // 使用更长的状态对象生命周期管理
                    var timerState = new object();
                    var timer = new Timer(callback, timerState, interval, Timeout.InfiniteTimeSpan);
                    _timers[scheduleName] = timer;
                    _logger.LogInformation("成功为计划 '{ScheduleName}' 设置定时器，将在 {Minutes} 分钟后触发", 
                        scheduleName, interval.TotalMinutes.ToString("F2"));
                }
                else
                {
                    _logger.LogWarning("无法为计划 '{ScheduleName}' 确定下一次备份时间，可能没有有效的备份时间点", scheduleName);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "安排每日备份时发生异常: {ScheduleName}, 错误: {Message}", scheduleName, ex.Message);
            }
        }

        /// <summary>
        /// 执行备份操作
        /// </summary>
        private async Task ExecuteBackupAsync(string scheduleName)
        {
            try
            {
                _logger.LogInformation("准备执行备份: {ScheduleName}", scheduleName);
                
                // 使用作用域来获取需要的服务
                using (var scope = _scopeFactory.CreateScope())
                {
                    // 获取备份计划服务
                    var scheduleService = scope.ServiceProvider.GetRequiredService<IBackupScheduleService>();
                    
                    // 获取计划ID
                    var dbSchedules = await scheduleService.GetAllSchedulesAsync();
                    var schedule = dbSchedules.FirstOrDefault(s => s.Name == scheduleName);
                    
                    if (schedule != null)
                    {
                        // 通过BackupScheduleService执行备份，这样可以自动记录历史
                        _logger.LogInformation("找到备份计划，开始执行备份操作: {ScheduleName}", scheduleName);
                        await scheduleService.ExecuteScheduleNowAsync(schedule.Id);
                    }
                    else
                    {
                        _logger.LogError("找不到名为 '{ScheduleName}' 的备份计划", scheduleName);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "执行备份时发生异常: {Message}", ex.Message);
            }
        }

        /// <summary>
        /// 启动备份服务
        /// </summary>
        public void StartService()
        {
            try
            {
                _logger.LogInformation("开始启动备份服务");
                
                // 确保备份调度服务已初始化
                if (_backupSchedulerService == null)
                {
                    CreateBackupSchedulerService();
                }
                
                // 启动服务
                if (_backupSchedulerService != null)
                {
                    _backupSchedulerService.Start();
                }
                
                // 启动所有定时器
                StartAllTimers();
                
                _logger.LogInformation("备份服务已成功启动");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "启动备份服务时发生异常: {Message}", ex.Message);
                throw;
            }
        }

        /// <summary>
        /// 停止备份服务
        /// </summary>
        public void StopService()
        {
            try
            {
                _logger.LogInformation("开始停止备份服务");
                
                // 停止所有定时器
                StopAllTimers();
                
                // 停止服务
                if (_backupSchedulerService != null)
                {
                    _backupSchedulerService.Stop();
                }
                
                _logger.LogInformation("备份服务已成功停止");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "停止备份服务时发生异常: {Message}", ex.Message);
                throw;
            }
        }
    }
}